-- $Id: $
-- File name:   TCU.vhd
-- Created:     11/28/2010
-- Author:      Alyssa Welles
-- Lab Section: 337-04
-- Version:     1.0  Initial Design Entry
-- Description: Transmitter Control Unit for INTERCEPTOR


LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_arith.ALL;
USE IEEE.std_logic_unsigned.ALL;

ENTITY TCU IS
  Port ( CLK : in std_logic;
       RST_N : in std_logic;
       EMPTY : in std_logic;
         LOG : in std_logic;
     R_ERROR : in std_logic;
SHIFT_ENABLE : in std_logic;
  SHIFT_UPDT : in std_logic;
    CRC_FLAG : in std_logic;
    R_ENABLE : out std_logic    
        );
end TCU;



architecture Behavioral of TCU is
  type state_type is (IDLE, TSM1, TSM2, TSM3, TSM_ENE, TSM_ER);
  signal state,nextstate : state_type;
  signal count,nextcount : std_logic_vector(3 downto 0);

begin

--------------------------------------------------------------------
--********************** STATE REGISTER **************************--
--------------------------------------------------------------------
 
 TCU_Reg: process (CLK, RST_N)
 begin
   if (RST_N='0') then
     state <= IDLE;
   elsif (CLK'event and CLK='1') then
     state <= nextstate;
   end if;
 end process TCU_Reg;
 
--------------------------------------------------------------------
--********************** COUNTER REGISTER ************************--
--------------------------------------------------------------------
 
 cntReg : process (CLK, RST_N)
 begin
   if (RST_N = '0') then
     count <= (others => '0');
   elsif (CLK'event and CLK = '1') then
     count <= nextcount;
   end if;
 end process cntReg;
 
--------------------------------------------------------------------
--********************** CLOCK COUNTER ***************************--
--------------------------------------------------------------------
 
 addcnt: process (SHIFT_ENABLE, SHIFT_UPDT, count)
 begin
   if SHIFT_ENABLE = '1' AND SHIFT_UPDT = '1' then
     nextcount <= count + 1;
   elsif count = "1000" then
     nextcount <= "0000";
   else
     nextcount <= count;
   end if;
 end process addcnt;  

--------------------------------------------------------------------
--********************** NEXT STATE LOGIC ************************--
--------------------------------------------------------------------
 
 NxStLogic : process (count, EMPTY, LOG, R_ERROR, SHIFT_ENABLE, state)
 begin
  CASE state IS
   WHEN IDLE =>       -- IDLE STATE
    IF R_ERROR = '1' THEN
     nextstate <= TSM_ER;
    ELSIF EMPTY = '0' THEN
     nextstate <= TSM1;
    ELSE 
     nextstate <= IDLE;
    END IF;   
    
   WHEN TSM1 =>
    nextstate <= TSM2; 
    
   WHEN TSM2 =>       -- BIT STUFFING CHECK
    IF R_ERROR = '1' THEN
     nextstate <= TSM_ER;
    ELSIF count = "1000" THEN
     nextstate <= TSM3;
    ELSE
     nextstate <= TSM2;
    END IF;  

   WHEN TSM3 =>       -- ERROR CHECK STATE
    IF R_ERROR = '1' THEN
     nextstate <= TSM_ER;
    ELSIF LOG = '1' THEN 
     nextstate <= TSM_ENE;
    ELSE 
     nextstate <= TSM3;
    END IF; 
    
   WHEN TSM_ENE =>    -- NORMAL TRANSMISSION
    IF R_ERROR = '1' THEN
     nextstate <= TSM_ER;
    ELSE
     nextstate <= IDLE;
    END IF;
    
   WHEN TSM_ER =>     -- ERROR DETECTED
    IF R_ERROR = '1' THEN
      nextstate <= TSM_ER;
    ELSE
     nextstate <= IDLE;
    END IF;
    
   WHEN others =>
    nextstate <= IDLE;
    
  END CASE;
 end process NxStLogic;

--------------------------------------------------------------------
--********************** OUTPUT LOGIC ****************************--
--------------------------------------------------------------------

 OutLogic : process (state)
 begin
  CASE state IS
   WHEN IDLE =>       -- IDLE STATE
     R_ENABLE <= '0';
   WHEN TSM1 =>       -- BIT STUFFING CHECK
     IF CRC_FLAG = '1' THEN
       R_ENABLE <= '0';
     ELSE
       R_ENABLE <= '1';
     END IF;
   WHEN TSM2 =>
     R_ENABLE <= '0';
   WHEN TSM3 =>       -- ERROR CHECK STATE
     R_ENABLE <= '0';
   WHEN TSM_ENE =>    -- NORMAL TRANSMISSION
     R_ENABLE <= '0';
   WHEN TSM_ER =>     -- ERROR DETECTED
     R_ENABLE <= '0';
   WHEN others =>
     R_ENABLE <= '0';
  END CASE;
 END process OutLogic; 

END Behavioral;
